#include "Game.h"
#include "GameLoop.h"

#include "Utils/Timer.h"
#include "Input/Input.h"
#include "Settings.h"
#include "Graphics/GraphicsBase.h"
#include "HUD.h"

#include <SDL/SDL.h>
#include <GL/gl.h>

#include "Menu/MainMenuPage.h"
#include "Menu/OptionsPage.h"

Game& Game::instance() {
    static Game game;
    return game;
}

Game::Game() : current_page("main"), done(false) {
}

Game::~Game() {
//need to free the MenuPages?
}

void Game::addPage(std::string name, MenuPage* page){
    menu[name] = page;
}

void Game::initialise() {
    
    // initialise list of menu pages
    menu["main"] = new MainMenuPage();
    menu["options"] = new OptionsPage();

    std::cerr << "initialising key bindings\n";

    Input::instance().registerBinding("activate_menu", "<enter>");
    Input::instance().registerBinding("activate_menu", "<mouse_left>");
    Input::instance().registerBinding("menu_up", "<up>");
    Input::instance().registerBinding("menu_down", "<down>");
    Input::instance().registerBinding("menu_scroll_up", "<scroll_up>");
    Input::instance().registerBinding("menu_scroll_up", "i");
    Input::instance().registerBinding("menu_scroll_down", "<scroll_down>");
    Input::instance().registerBinding("menu_scroll_down", "k");

    std::cerr << "initialising game\n";
//    Input::instance.registerKeybinding("","");
//    GameLoop::initialise();
}

void Game::execute() {

    while (!done) {
        Timer::update();
        pollEvents();
        if(Input::instance().isKeyDown("quit")){
            done = true;
        }

        update();

        if(Input::instance().isKeyDownAndClear("activate_menu")) {
            activate();
        }

        if(Settings::instance().getIntValue("graphics", "render")){
            render();
        }
    }
}

void Game::activate() {
    MenuPage* mp = menu[current_page];
    if (mp)
        mp->activate();
}

void Game::pollEvents (void) {
    SDL_Event event;
    // handle the events in the queue
    while(SDL_PollEvent(&event)){
        switch(event.type){

            case SDL_KEYDOWN:
                Input::instance().updateKey(event.key.keysym.sym, true);
                break;
            case SDL_KEYUP:
                Input::instance().updateKey(event.key.keysym.sym, false);
                break;
            case SDL_MOUSEBUTTONDOWN:
//                std::cerr << "button down " << (int)event.button.button << std::endl;
                Input::instance().updateMouseButton((int)event.button.button, true);
                break;
            case SDL_MOUSEBUTTONUP:
//                std::cerr << "button up " << (int)event.button.button << std::endl;
                if (!((int)event.button.button == 4 || (int)event.button.button == 5)) {
                    Input::instance().updateMouseButton((int)event.button.button, false);
                }
                break;

            case SDL_QUIT:
                // handle quit requests
                done = true;
                break;

            default:
                break;
        }
    }
}


void Game::update() {
    MenuPage* mp = menu[current_page];
    if (mp)
        mp->update();
}

void Game::render() {
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glLoadIdentity();
    
//    glPushMatrix();
//    glTranslatef(0.0f, 0.0f, -GraphicsBase::getCameraHeight() );

//    Vector2D focus = World::instance().getCurrentFocusPoint();
//    glTranslatef(-focus.x, -focus.y, 0.0f);
//    World::instance().render();
//    HUD::instance().renderCursor();
//    glPopMatrix();

//    HUD::instance().renderHUD();
//
//
//
//    render menu similar to how you render the HUD
    GraphicsBase::switchToOrthographic();

    // render the current page

    MenuPage* mp = menu[current_page];
    if (mp)
        mp->render();

    HUD::instance().renderCursorOrtho();
    
    GraphicsBase::switchFromOrthographic();

    // Draw it to the screen */
    SDL_GL_SwapBuffers( );
}

void Game::playGame() {
    GameLoop::initialise();
    GameLoop::execute();
    GameLoop::shutdown();
}

void Game::exit() {
    done = true;
}
void Game::goToMenuPage(std::string page) {
    current_page = page;
}
